查看原文
其他

客户之声|携程基于 OceanBase 读写分离方案的探索与优化

乐于分享的 OceanBase 2022-08-27

本文转载自“博客园”,点击文末“阅读原文”跳转原文,作者 许金柱和台枫。


许金柱:携程资深 DBA,专注于分布式数据库研究及运维


台枫:携程高级 DBA,主要负责 MySQL 和 OceanBase 的运维


数据库的读写分离策略是一种将数据库的查询操作和写入操作分离的方案,目的是降低读写操作的相互影响并提升资源利用率。在携程,读写分离的应用场景非常普及,只读的业务场景主要包括 BI 查询业务、大数据 ETL 取数、缓存的拉取等。


OceanBase 数据库天然支持读写分离的功能,即通过 OBProxy 代理服务和修改 OBServer 的配置即可实现业务的读写分离策略;然而 OceanBase 读写分离方案存在与业务耦合度过高、匹配不够灵活等问题。因此,我们在 OceanBase 已有的读写分离方案下继续探索并优化更符合当前业务场景的解决方案。



OceanBase 原生的读写分离策略


OceanBase 数据库在读取数据时,提供了两种一致性级别:强一致性和弱一致性。


强一致性是指请求路由给主副本读取最新数据;弱一致性是指请求优先路由给备副本,不要求读取最新数据。


基于此,通过应用侧为执行的 SQL 添加 SQL Hint 来显性开启弱一致性读就可以实现基于注释的读写分离功能,同时也衍生出如下三种常用的读写分离策略:


策略一:备优先读


通过修改 OBproxy 的路由策略为 follower_first ,并将业务读流量指定到该 OBProxy 从而保证读请求优先访问 follower 副本。



优点:配置相对简单,只修改 OBProxy 配置,无需修改 OBserver 配置;读流量均摊到全部 follower 副本上。


缺点:读请求可能存在跨 zone 访问;在不调整副本 leader 的情况下,同 zone 或同 server 下不同副本的 leader 和 follower 可能共存,不能完全实现 zone 级别或者 server 级别的读写隔离。


高可用:当两个 follower 副本中的一个宕机时,配置读写分离的 OBProxy 将优先路由读请求到另一个 follower 副本。


策略二:LDC(Logical Data Center)只读型副本


新增一个只读副本,为其添加 idc 标签,并将 OBProxy 的参数 proxy_idc_name 指向该 idc。在业务层面,指定读流量访问该 OBProxy ,通过 LDC 配置仅访问只读副本。



优点:读写完全隔离,读扩展性好。


缺点:只读型副本只同步数据,不参与分布式选举,需要额外增加一个副本。对业务读请求远小于写请求的场景可能存在资源浪费。


高可用:当只读副本宕机时,已经配置了读写分离策略的 OBProxy 将自动把流量切到其他 follower 副本上。


适用场景:业务读请求远大于写请求,且大部分读请求对实时性要求不高或者有大量的 AP 分析场景。


策略三:LDC(Logical Data Center)全功能型副本


迁出全功能副本的 leader ,使该副本只有非 leader 的角色存在,同时在该副本添加一个 IDC 标签,将 OBProxy 的参数 proxy_idc_name 指向该 IDC 标签。在业务层面,指定读流量访问该 OBProxy ,通过 LDC 配置仅访问该副本,实现读写流量完全分离。



优点:读写流量完全隔离,且相对于策略二不需要额外资源


缺点:leader 分布集中在两个 zone 中,有可能会影响写入性能


高可用性:当指定 idc 侧的 follower 副本宕机时,配置读写分离的 OBproxy 将自动路由到其他 follower 副本上


适用场景:读写比较均衡,存在少量分析场景


在满足读写分离需求的同时,我们也关心在使用这些策略时的集群高可用性:


当只读节点宕机时,配置读写分离的 OBProxy 将自动修改路由,优先将读流量路由到其他 follower 副本上。在使用策略二或者策略三时,每一个 partition 只有单个的 readonly 或者 follower 副本承担读压力,因此切换到新的 follower 副本上的读写请求是可以负担的。


当配置读写分离的 OBProxy 出现问题时,由于 OBProxy 是一组无状态的服务,因此只需要依赖数据库访问中间件的判活机制来修改应用访问 OBproxy 的入口即可实现高可用。



初探读写分离场景


上面三种策略在不同场景下各有优劣,也都能实现读写分离的效果,但相较于前两种策略,我们更倾向于使用策略三。因为携程的业务场景与策略三的适用场景更贴合,且成本相对较低。


同时,我们也关注到 OceanBase 现有的读写分离策略中存在一个共性问题:应用侧必须为 SQL 添加弱一致性读的 SQL Hint,否则即使在 OBProxy 做了相应配置,仍然不能达到读写分离的效果,即所有读写压力将集中在 leader 副本上。如果使用 OceanBase 原生的读写分离方案会带来两个问题。第一,用户需要进行代码改造会带来额外的工作量;第二,原生的读写分离策略与应用的耦合度高。因此,我们需要在已有方案的基础上,根据当前业务场景探索并实践出一个灵活的、与应用耦合度低的读写分离策略。

携程目前已接入 OceanBase 近百套集群,租户约 140 个,同时越来越多基于 MySQL 数据库的业务计划迁移至 OceanBase 数据库。


针对需要保证 OceanBase 数据库适配当前读写分离场景的需求,我们首先梳理了携程业务目前读写分离的主要适用场景:


  • ETL 取数:Zeus 定时作业,需要将线上订单相关数据同步至 Hive 或 ES


  • BI 查询 Offline 报表,为业务部门提供分析数据


  • MySQL 业务中已存在的读写分离场景(如缓存拉取): 读请求远大于写请求的产品库场景,要求在延迟阈值内,将读请求路由到只读节点


我们看到携程现有的读写分离场景包含 OLTP 和 OLAP ,并且数据库涉及的业务线比较复杂且难分辨。


同时,读写分离改造涉及到增加 SQL Hint  /*+READ_CONSISTENCY(WEAK) */ 的问题 。SQL Hint 在传统的关系型数据库中是一种通过注释的方式改写 SQL 执行计划的设计,而在 OceanBase 中它同样有类似功能,并且提供了 SQL 选择副本访问策略的能力。为了使弱一致性读生效,需要对有读写分离需求应用中的 SQL 做如下改造:


  • MySQL 原版 SQL 


SELECT * FROM test


  • OceanBase 改造读写分离的 SQL


SELECT /*+READ_CONSISTENCY(WEAK) */ * FROM test


综上,在携程的业务上线或迁移过程中,容易遇到以下问题:


  • 现有业务迁移过程不透明,涉及业务层面的代码改造。


  • 代码和读写分离策略耦合,造成技术债。


  • DBA 需要重新审核查询语句和业务行为,给出改造评估建议。


针对这些痛点,我们希望可以不使用 SQL Hint ,直接指定这些 SQL 进行弱一致性读来达到读写分离的目的。我们开始调研能否在 OceanBase 代码层寻求解决方案。通过对源码研究,我们尝试在 OBProxy 组件上进行改造,最终实现不涉及用户代码改造前提下的自动开启弱一致性读功能。


代码的改造包含以下两个方面:


  • 功能1:自动为访问本 OBProxy 的所有连接开启弱一致性读策略


  • 功能2:自动为访问本 OBProxy 的指定帐号(只读账号)开启弱一致性读策略


我们通过新增两个参数 enable_weak_read 和 weak_read_user_list 在建立连接时进行判断来分别实现上述两个功能。当 enable_weak_read 参数开启时,将为访问该 OBProxy 的所有连接开启弱一致性读;weak_read_user_list 参数则针对账号维度来开启弱一致性读。



以上弱一致性读策略均基于会话级别开启,通过配置 LDC 和 read(slave) 域名进行读、写隔离且分担 leader 副本压力,自动实现读写分离策略,不需要人工干预。



读写分离场景的实践和测试


对 OBProxy 进行改造后,为了验证其功能性,我们将其与 LDC(Logical Data Center)全功能型副本读写分离策略相结合,进行了如下实验。


场景一:


当业务正常进行读请求时,将 leader 副本集中在 zone1,一段时间后,OBProxy 指定账号开启弱一致性读并且绑定 idc2(zone2+zone3)



实验结果:zone1 的读流量消失,读流量被 zone2 和 zone3 分摊



场景二:


当业务正常进行读请求时,Leader 副本集中在 zone1 和 zone3,一段时间后,OBProxy 对所有连接开启弱一致性读,并绑定 idc2(zone2)



实验结果:zone1 和 zone3 的读流量消失,读流量全部由 zone2 承担




携程选择的 OceanBase 读写分离场景


在携程现有的读写分离场景中,我们通过区分业务的账号来识别业务的行为,因此我们针对部分账号开启弱一致性读,并通过绑定其中一个 zone 和 OBProxy 来将这部分请求路由到指定 zone 上实现读写分离。



优点:


  • 同一个集群的 OBProxy 配置统一(不开启弱一致性读时 LDC 路由不生效),便于 OBProxy 的横向扩展和快速切换应用流量的指向。


  • 按照账号维度配置灵活度高,在部分极端场景方便人工介入。



我们根据现有 OceanBase 的读写分离方案通过优化 OBProxy 源码,新增 enable_weak_read 和 weak_read_user_list 两个功能,在 OBProxy 上直接实现读写流量的分离,解决了 MySQL 迁移 OceanBase 过程不透明、用户代码与原读写分离方案耦合度高等痛点,推动分布式数据库 OceanBase 适配携程当前业务场景,同时更好地在携程落地,走出扎实的一步。


往期推荐:




对话ACE第三期:数据库技术生态应如何构建


六月征文特别企划|分享您与 OceanBase 的第一次


满足未来8-10年业务需求,云南红塔银行核心系统升级


特别的儿童节,OceanBase 送上一份特别的惊喜

这里,查看博客原文!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存